<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>example-vanilla</title>
  </head>
  <body style="height: 2000px">
    <script type="module" src="/main.ts"></script>
    <!-- <script type="module" src="/index.ts"></script> -->
    <div id="app"></div>

    <!-- Event 点击事件捕捉 -->
    <div>
      <div>Event 点击事件捕捉</div>
      <div
        style="border: 1px solid green; height: 200px; padding: 10px"
        class="sss xxx 111 vvv"
        data-warden-title="xxx"
        data-warden-bigTitle="bigTitle"
        width="100%"
        id="222"
        sdfasd
      >
        <div
          style="border: 1px solid red; height: 100px; padding: 10px"
          data-warden-test="test"
          data-warden-title="titletitle"
          data-warden-bing="bing"
          data-warden-event-id="ddd"
        >
          <!-- <img src="../../public/face.jpg" alt="" /> -->
          <div style="border: 1px solid rgb(71, 1, 236)">asdasdasd</div>
        </div>
        <div data-warden-id="我是ID">
          <button value="xxxxxx" ref="bun">1111</button>
        </div>
      </div>
    </div>
    <br />

    <!-- Error 捕捉 -->
    <div>
      <div>Error 捕捉</div>
      <button id="codeErr">代码错误</button>
      <!-- <button id="codeErr" onclick="codeError()">代码错误</button> -->
      <button id="promiseError" onclick="promiseError()">promiseError</button>
      <button id="consoleErr" onclick="consoleErr()">手动输出错误</button>
    </div>
    <script>
      // ---------------- Error 捕捉 ----------------
      document.getElementById("codeErr")?.addEventListener("click", () => {
        codeError();
      });

      function codeError() {
        const a = {};
        a.split("/");
      }
      function promiseError() {
        const promiseWrap = () =>
          new Promise((resolve, reject) => {
            reject("promise reject");
          });
        promiseWrap().then((res) => {
          console.log("res", res);
        });
      }
      function consoleErr() {
        console.error("consoleErr1", "consoleErr1.1", "consoleErr1.2");
        // console.error(111);
        // console.error(new Error("谢谢谢谢谢"));
      }
    </script>

    <br />

    <!-- 批量 Error -->
    <div>
      <div>批量 Error 捕捉</div>
      <button onclick="batchErrorA(10)">立即触发代码错误-10条</button>
      <button onclick="batchErrorA(100)">立即触发代码错误-100条</button>
      <br />
      <br />
      <button onclick="batchErrorAT(20)">异步触发代码错误-20条</button>
      <button onclick="batchErrorAT(100)">异步触发代码错误-100条</button>
      <br />
      <br />
      <button onclick="batchErrorB(10)">
        立即触发[reject-10条 + 代码错误-10条 + console.error-10条]
      </button>
      <button onclick="batchErrorB(20)">
        立即触发[reject-20条 + 代码错误-20条 + console.error-20条]
      </button>
      <br />
      <br />
      <button onclick="batchErrorC(10)">
        异步触发[reject-10条 + 代码错误-10条 + console.error-10条]
      </button>
      <br />
      <br />
      <button onclick="batchErrorD()">异步触发无限错误</button>
    </div>
    <script>
      function batchErrorA(num) {
        for (let x = 1; x <= num; x++) {
          document.getElementById("codeErr").click();
        }
      }
      function batchErrorAT(num) {
        for (let x = 1; x <= num; x++) {
          setTimeout(() => {
            document.getElementById("codeErr").click();
          }, x * 300);
        }
      }
      function batchErrorB(num) {
        for (let x = 1; x <= num; x++) {
          document.getElementById("codeErr").click();
          consoleErr();
          promiseError();
        }
      }
      function batchErrorC(num) {
        for (let x = 1; x <= num; x++) {
          setTimeout(() => {
            batchErrorB(1);
          }, x * 300);
        }
      }
      function batchErrorD() {
        setInterval(() => {
          document.getElementById("codeErr").click();
        }, 200);
      }

      // function groupArray(arr, ...keys) {
      //   const groups = new Map();
      //   for (const obj of arr) {
      //     const keyArr = keys.filter(k => obj[k]).map(k => obj[k]);

      //     // if (keyArr.length !== keys.length) return undefined
      //     const key = keyArr.join(':')
      //     console.log('key', key);
      //     if (!groups.has(key)) {
      //       groups.set(key, []);
      //     }
      //     groups.get(key).push(obj);
      //   }
      //   return Array.from(groups.values());
      // }

      // // 示例代码
      // const arr = [
      //   { name: 'apple', category2: 'fruit', price: 1.5 },
      //   { name: 'apple', category: 'fruit', price: 1 },
      //   { name: 'carrot', category: 'vegetable', price: 2 },
      //   { name: 'carrot', category: 'vegetable', price: 1.8 },
      //   { name: 'orange', category: 'fruit', price: 2 },
      // ];

      // const groups = groupArray(arr, 'name', 'category');
      // console.log(groups);
    </script>

    <br />

    <!-- Http 事件捕捉 -->
    <div>
      <div>Http 事件捕捉</div>
      <button id="normalReq" onclick="onClickXhrNormal()">xhr正常请求</button>
      <button id="exceptionReq" onclick="onClickXhrError()">xhr异常请求</button>
      <button id="normalFetch" onclick="onClickNativeFetch()">
        Fetch正常请求
      </button>
      <button id="exceptionFetch" onclick="onClickNativeErrorFetch()">
        Fetch异常请求
      </button>
    </div>
    <script>
      // ---------------- Http 事件捕捉 ----------------
      function onClickXhrNormal() {
        const xhr = new XMLHttpRequest();
        xhr.open("get", "/normal");
        xhr.setRequestHeader("content-type", "application/json");
        xhr.send();
        xhr.onreadystatechange = function () {
          if (xhr.readyState === 4) {
            console.log("请求成功", xhr.responseText.slice(0, 10));
          }
        };
      }
      function onClickXhrError() {
        const xhr = new XMLHttpRequest();
        xhr.open("get", "/exception");
        xhr.setRequestHeader("content-type", "application/json");
        xhr.send();
        xhr.onreadystatechange = function () {
          if (xhr.readyState === 4) {
            console.log("请求成功", xhr.responseText.slice(0, 10));
          }
        };
      }
      function onClickNativeFetch() {
        fetch("/normal/post", {
          method: "POST",
          body: JSON.stringify({ test: "测试请求体" }),
          mode: "cors",
          headers: {
            "Content-Type": "application/json",
          },
        })
          .then((res) => res.text())
          .then((res) => {
            console.log("res----res", res);
          })
          .catch((err) => console.log("err----err", err));
      }
      function onClickNativeErrorFetch() {
        fetch("/exception/post", {
          method: "POST",
          body: JSON.stringify({ test: "测试请求体" }),
          mode: "cors",
          headers: {
            "Content-Type": "application/json",
          },
        })
          .then((res) => res.text())
          .then(
            (res) => {
              console.log("res", res);
            },
            (err) => {
              console.log("err", err);
            }
          );
      }
    </script>

    <br />

    <!-- Pv 事件捕捉 -->
    <div>
      <div>Pv 事件捕捉</div>
      <!-- 这种页面内的可以捕捉 -->
      <!-- <a href="/#/edit">hash跳转</a> -->
      <button onclick="hashChange()">hash跳转</button>
      <button onclick="historyPushState()">history push跳转</button>
      <button onclick="historyReplaceState()">history replace跳转</button>
      <!-- <a href="/vue2/index.html">跳到Vue2页面</a> -->
      <!-- <a href="/vue3/index.html">跳到Vue3页面</a> -->

      <!-- 这种无法捕捉 -->
      <a href="http://www.baidu.com" target="_blank">跳到百度</a>
    </div>
    <script>
      // ---------------- Pv 事件捕捉 ----------------
      function hashChange() {
        // window.open('https://www.baidu.com') // 这种无法捕捉
        // window.open('/#/edit') // 这种可以捕捉到，不过也是在新开的地方进来才能捕捉，并不是跳走阶段捕捉
        window.location.href = "/#/edit";
      }
      function historyPushState() {
        // window.history.pushState({}, "测试", `123`);
        window.history.pushState(
          {},
          "测试",
          `${parseInt(Math.random() * 1000)}`
        );
      }
      function historyReplaceState() {
        window.history.replaceState(
          {},
          "测试",
          `${parseInt(Math.random() * 1000)}`
        );
      }
    </script>

    <br />

    <!-- 异步加载资源 -->
    <div>
      <div class="badge badge-pill badge-primary">Performance 异步加载资源</div>
      <button onclick="performanceAddScript()">插入正确Script</button>
      <button onclick="performanceAddScriptError()">插入错误Script</button>
      <br />
      <button onclick="performanceAddLink()">插入Link</button>
      <button onclick="performanceAddImg()">插入Img</button>
      <button onclick="performanceAddLocalImg()">
        插入Base64图片(不涉及请求所以无需采集)
      </button>
      <br />
      <button onclick="performanceAddXHR()">发送XMLHTTPRequest</button>
      <button onclick="performanceAddErrXHR()">发送错误XMLHTTPRequest</button>
      <div id="performance-img-div" />
      <button onclick="performanceAddFetch()">发送fetch</button>
      <button onclick="performanceAddFetchError()">发送错误fetch</button>
    </div>
    <script>
      function performanceAddScript() {
        const script = document.createElement("script");
        script.src = "https://cdn.jsdelivr.net/npm/lodash";
        document.head.appendChild(script);
      }
      function performanceAddScriptError() {
        const script = document.createElement("script");
        script.src = "https://cdn.jsdelivr.net/npm/lodash22";
        document.head.appendChild(script);
      }
      function performanceAddLink() {
        const link = document.createElement("link");
        link.type = "text/css";
        link.rel = "stylesheet";
        link.href = "https://ahooks.js.org/useExternal/bootstrap-badge.css";
        document.head.appendChild(link);
      }
      function performanceAddImg() {
        const img = document.createElement("img");
        img.src = `https://cdn.staticaly.com/gh/M-cheng-web/image-provider@main/blog/Annapurna-Ranges-2560x1440.5r9m9t5vg1g0.webp`;
        const div = document.getElementById("performance-img-div");
        div.style = "width: 400px; height: 400px; overflow: hidden;";
        div.appendChild(img);
      }
      function performanceAddLocalImg() {
        const img = document.createElement("img");
        img.src =
          "";
        const div = document.getElementById("performance-img-div");
        div.style = "width: 100px; height: 100px; overflow: hidden;";
        div.appendChild(img);
      }
      function performanceAddXHR() {
        const xhr = new XMLHttpRequest();
        xhr.open("get", `/index.html?t=${Date.now()}`);
        xhr.send();
      }
      function performanceAddErrXHR() {
        const xhr = new XMLHttpRequest();
        xhr.open("post", "/not-found");
        xhr.send(JSON.stringify({}));
      }
      function performanceAddFetch() {
        window.fetch(`/index.html?t=${Date.now()}`, {
          method: "GET",
          header: {
            "Content-Type": "application/json;charset=UTF-8",
          },
        });
      }
      function performanceAddFetchError() {
        window.fetch(`/index.html22?t=${Date.now()}`, {
          method: "GET",
          header: {
            "Content-Type": "application/json;charset=UTF-8",
          },
        });
      }
    </script>

    <br />

    <!-- 延迟加载sdk -->
    <div>
      <div>延迟加载sdk</div>
      <button onclick="delayInit()">延迟加载sdk</button>
    </div>
    <script type="module">
      import { init } from "@web-tracing/core";
      window.delayInit = function () {
        init({
          // dsn: 'https://cdn.staticaly.com/gh/M-cheng-web/image-provider@main/blog/Annapurna-Ranges-2560x1440.5r9m9t5vg1g0.webp',
          dsn: "http://1.15.224.10:22/trackweb/tra",
          appName: "cxh",
          debug: true,
          pv: true,
          performance: true,
          error: true,
          event: true,
          cacheMaxLength: 10,
          cacheWatingTime: 1000,
        });
      };
    </script>

    <br />

    <!-- 手动发送缓存事件 -->
    <div>
      <div>手动发送缓存事件</div>
      <button onclick="sendLocal()">点击发送</button>
    </div>
    <script type="module">
      import { sendLocal, setLocalizationOverFlow } from "@web-tracing/core";
      window.setLocalizationOverFlow = function () {
        setLocalizationOverFlow((data) => {
          console.log(
            "本地化存储超过最大容量，此data为最后一次数据，请及时清空本地存储空间并保存此data（可以调用sendLocal发送后再把此data数据手动存储在localstorage）",
            data
          );
        });
      };
      window.setLocalizationOverFlow();
      window.sendLocal = function () {
        sendLocal();
      };
    </script>

    <br />

    <!-- 曝光采集 -->
    <div>
      <div>曝光采集</div>
      <button onclick="intersectionDisconnect()">取消所有采集曝光</button>
      <button onclick="intersectionObserver('target')">采集图片的曝光</button>
      <button onclick="intersectionUnobserve('target')">取消采集曝光</button>
      <div id="target">
        <img
          src="https://aecpm.alicdn.com/simba/img/TB183NQapLM8KJjSZFBSutJHVXa.jpg"
        />
      </div>
      <br />
      <button onclick="intersectionObserver('target2')">采集图片的曝光</button>
      <button onclick="intersectionUnobserve('target2')">取消采集曝光</button>
      <div id="target2">
        <img
          src="https://aecpm.alicdn.com/simba/img/TB183NQapLM8KJjSZFBSutJHVXa.jpg"
        />
      </div>
    </div>
    <script type="module">
      import {
        intersectionObserver,
        intersectionUnobserve,
        intersectionDisconnect,
      } from "@web-tracing/core";
      window.intersectionObserver = function (str) {
        const target = document.querySelector(`#${str}`);
        intersectionObserver({
          target,
          threshold: 0.5, // 曝光的临界点 (0.5表示移入窗口一半算做开始曝光、移出窗口一半算结束曝光)
          params: { name: 1111, targetName: str }, // 附带的额外参数
        });
      };
      window.intersectionUnobserve = function (str) {
        const target = document.querySelector(`#${str}`);
        intersectionUnobserve(target);
      };
      window.intersectionDisconnect = function () {
        intersectionDisconnect();
      };
    </script>
    <script>
      // const target = document.querySelector("#target");
      // const io = new IntersectionObserver(
      //   (entries) => {
      //     entries.forEach((entry) => {
      //       // 如果该元素是可见，就执行某些操作
      //       if (entry.isIntersecting) {
      //         console.log("目标元素已经曝光");
      //       } else {
      //         console.log("目标元素已经离开");
      //       }
      //     });
      //   },
      //   {
      //     root: null,
      //     threshold: 1, // 阀值设为1，当只有比例达到1时才触发回调函数
      //   }
      // );
      // // 开始观察目标元素
      // io.observe(target);
    </script>

    <br />

    <script>
      // window.addEventListener("offline", () => {
      //   console.log("已断网");
      // });
      // window.addEventListener("online", () => {
      //     console.log("网络已连接");
      // });
    </script>
  </body>
</html>
